package Jvm;

/**
 * lock的四种用法 :<br/>
 * <b> 1.</b>方法声明上加synchronized 锁住当前方法
 * ,其他线程可以访问该对象的另外的不是用synchronized锁住的方法(包括没加锁的方法和用LockTest.class锁的方法)<br/>
 * <b>2.</b>方法内用 synchronized(lock)
 * 锁住指定资源.其他方法用到该lock的方法,都不能呗别的线程调用.其他lock或者使用synchronized的方法 ,其他线程可以访问<br/>
 * <b> 3</b>.方法内使用 synchronized(this) 使用当前对象进行加锁.意义等同于在方法上用snychronized关键字.
 * synchronized和this其实是一个概念.只是锁的范围不一样.方法上关键字锁住了整个方法.方法内用this加锁,锁住的是代码块.<br/>
 * <b>4.</b>方法内使用snychronized(T.class)加锁,是一个普通的加锁.jvm中所有使用该类.class 进行加锁的方法
 * ,都会被阻塞.另外注意,<br/>
 * <b>要注意</b>
 * 如果方法上用的是static修饰,两个方法都有synchronized,那么这个锁将是全局锁.不是针对某一个对象,是这个class的所有对象
 * ,都会被串行化. 如果方法中用synchronized(T.clsss) ,也意味着讲jvm该T类型的所有实例的对该方法的访问串行化. <br/>
 *
 * 所以(以T类为例) : public static void snychronized sayHello(){} 等同于: public void
 * sayIHello(){ synchronized(T.class) }
 *
 * @author kai
 *
 */
public class LockTest {
    public static void main(String[] args) {
        lockedObject lo = new lockedObject();
        lockedObject lo2 = new lockedObject();
        aThread aThread = new aThread(lo);
        bThread bThread = new bThread(lo2);

        aThread.start();
        bThread.start();
    }

}

class aThread extends Thread {
    private lockedObject object;

    public aThread(lockedObject object) {
        this.object = object;
    }

    @Override
    public void run() {
        object.getname();
    }
}

class bThread extends Thread {
    private lockedObject object;

    public bThread(lockedObject object) {
        this.object = object;
    }

    @Override
    public void run() {
        object.getnamename();
    }
}

class lockedObject {
    private String name;
    private Object lock = new Object();

    // lock metho
    public static synchronized void getname() {
        System.out.println("name is jack");
        sleepUtil.sleep(4);
    }

    // lock metho
    public static synchronized void getnamename() {
        System.out.println("name is jack");
        sleepUtil.sleep(4);
    }

    // lock a objcet
    public void getname2() {
        synchronized (lock) {
            System.out.println("this is name2");
            sleepUtil.sleep(4);
        }
    }

    public void getname22() {
        synchronized (lock) {
            System.out.println("this is name22");
            sleepUtil.sleep(4);
        }
    }

    // lock a class
    public void getname3() {
        System.out.println("this is name3 before");
        synchronized (this) {
            System.out.println("this is name3");
            sleepUtil.sleep(4);
        }
    }

    // lock all class
    public void getname4() {
        synchronized (lockedObject.class) {
            System.out.println("this is name4");
            sleepUtil.sleep(4);
        }
    }

    public void getname5() {
        synchronized (lockedObject.class) {
            System.out.println("this is name5");
            sleepUtil.sleep(4);
        }
    }

    public void getname44() {
        synchronized (LockTest.class) {
            System.out.println("this is name44");
            sleepUtil.sleep(4);
        }
    }

    // no lock
    public static void getnolock() {
        System.out.println("no lock");
        sleepUtil.sleep(4);
    }

}

class sleepUtil {
    public static void sleep(int time) {
        try {
            Thread.sleep(time * 1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
}